package org.rasterfun.utils.drag

import java.awt.event._
import java.awt.{Graphics2D, Color, Graphics}
import javax.swing.{JComponent, JPanel}

/**
 * Mixin that provides zoom and pan functionality for a JComponent.
 * 
 * @author Hans Haggstrom
 */
trait NavigationMixin extends JComponent with MouseEventMixin {

  def getPanX: Float = projectX(panX)
  def getPanY: Float = projectY(panY)
  def getScale: Float = scale

  private var panX = 0
  private var panY = 0
  private var scale = 1f

  addDragListener( RightMouse, new DragListener[Object] {
    override def drag(startX: Int, startY: Int, prevX: Int, prevY: Int, x: Int, y: Int, e: MouseEvent, draggedObject: Object) {
      panX += (x - prevX)
      panY += (y - prevY)
      notifyProjectionUpdated()
    }
  } )

  /**
   * Called when the user pans or zooms the view.
   * Defaults to calling repaint.
   */
  def onProjectionUpdated(xOffs: Float, yOffs: Float, xScale: Float, yScale: Float) {
    repaint()
  }

  override def mouseWheelRolled(roll: Int, e: MouseEvent) {
    scale = 0.1f max scale - roll * 0.1f
    notifyProjectionUpdated()
  }

  /**
   * Project screen x coordinate to canvas x coordinate.
   */
  def projectX( screenX : Int ) : Float = projectCoord( screenX, getWidth,  panX )

  /**
   * Project screen y coordinate to canvas y coordinate.
   */
  def projectY( screenY : Int ) : Float = projectCoord( screenY, getHeight, panY )

  private def notifyProjectionUpdated() {
    onProjectionUpdated(getPanX, getPanY, getScale, getScale)
  }

  private def projectCoord ( c : Int, size : Int, pan : Float ) : Float = (c.toFloat - size.toFloat / 2f - pan) / scale
}


